package com.wuze.sprintboot.netty.starter;

import com.wuze.sprintboot.netty.handler.IntercepterAdapter;
import com.wuze.sprintboot.netty.handler.HttpServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.wuze.sprintboot.netty.util.AppUtil.Interceptor_List;


public class NettyHttpServer{

    private static final Logger LOGGER = LoggerFactory.getLogger(NettyHttpServer.class);


    public void start(int port,HttpServerHandler httpServerHandler){

        ServerBootstrap bootstrap = new ServerBootstrap();
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        bootstrap.group(bossGroup,workerGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childOption(NioChannelOption.TCP_NODELAY, true);//是否使用Nagle算法，设置为true关闭Nagle算法。
        bootstrap.childOption(NioChannelOption.SO_REUSEADDR,true);//是否允许重用端口。默认值与系统相关。
        bootstrap.childOption(NioChannelOption.SO_KEEPALIVE,false);//是否使用TCP的心跳机制。
        bootstrap.childOption(NioChannelOption.SO_RCVBUF, 2048);//套接字使用的接收缓冲区大小
        bootstrap.childOption(NioChannelOption.SO_SNDBUF, 2048);//套接字使用的发送缓冲区大小
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new HttpServerCodec());
                ch.pipeline().addLast(new HttpObjectAggregator(512 * 1024));
                Interceptor_List.forEach(objs->{
                    ch.pipeline().addLast((IntercepterAdapter)objs);
                });
                ch.pipeline().addLast(httpServerHandler);
            }
        });
        ChannelFuture channelFuture = bootstrap.bind(port).syncUninterruptibly().addListener(future -> {
            String logBanner = "\n\n" +
                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
                    "*                                                                                   *\n" +
                    "*                                                                                   *\n" +
                    "*                   Netty Http Server started on port {}.                         *\n" +
                    "*                                                                                   *\n" +
                    "*                                                                                   *\n" +
                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n";
            LOGGER.info(logBanner, port);
        });

        channelFuture.channel().closeFuture().addListener(future -> {
            LOGGER.info("Netty Http Server Start Shutdown ............");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        });
    }
}
